package com.github.shiqiyue.app.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.util.*;

/***
 * 签名工具类
 * @author wenyao.wu
 * @date 2019/7/16
 */
@Slf4j
public class SignUtils {

    private static final URLCodec URL_CODEC = new URLCodec();

    private static final Logger logger = LoggerFactory.getLogger(SignUtils.class);


    private static final BitSet WWW_FORM_URL_SAFE = new BitSet(256);

    static {
        // alpha characters
        for (int i = 'a'; i <= 'z'; i++) {
            WWW_FORM_URL_SAFE.set(i);
        }
        for (int i = 'A'; i <= 'Z'; i++) {
            WWW_FORM_URL_SAFE.set(i);
        }
        // numeric characters
        for (int i = '0'; i <= '9'; i++) {
            WWW_FORM_URL_SAFE.set(i);
        }
        // special chars
        WWW_FORM_URL_SAFE.set('-');
        WWW_FORM_URL_SAFE.set('_');
        WWW_FORM_URL_SAFE.set('.');
        WWW_FORM_URL_SAFE.set('!');
        WWW_FORM_URL_SAFE.set('~');
        WWW_FORM_URL_SAFE.set('*');
        WWW_FORM_URL_SAFE.set('\'');
        WWW_FORM_URL_SAFE.set('(');
        WWW_FORM_URL_SAFE.set(')');
        // blank to be replaced with +

    }

    public static String base64Encode(String path) throws UnsupportedEncodingException {
        return org.apache.commons.codec.binary.StringUtils.newStringUsAscii(URLCodec.encodeUrl(WWW_FORM_URL_SAFE, path.getBytes(URL_CODEC.getDefaultCharset())));
    }

    /***
     * 获取Md5签名
     * @param params
     * @param appSecret
     * @return
     */
    public static String getMd5Sign(Map<String, String> params, String appSecret) {

        try {
            String content = getSignContent(params, appSecret);
            if(log.isDebugEnabled()){
                log.debug("content: {}",content);
            }
            content = base64Encode(content);
            if(log.isDebugEnabled()){
                log.debug("urlcodec content: {}",content);
            }
            String sign = DigestUtils.md5Hex(content);
            if(log.isDebugEnabled()){
                log.debug("sign:{}", sign);
            }
            return sign;
        } catch (Exception e) {
            logger.error("获取md5签名失败", e);
            return null;
        }

    }

    /**
     * 获取签名内容
     *
     * @param params
     * @return
     */
    private static String getSignContent(Map<String, String> params, String appSecret) {
        //移除签名值
        params.remove("sign");
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        int index = 0;
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = StringUtils.defaultIfBlank(params.get(key), StringUtils.EMPTY);
            if (StringUtils.isNotEmpty(key)) {
                content.append((index == 0 ? "" : "_") + key + "=" + value);
                index++;
            }
        }
        content.append("_").append(appSecret);
        return content.toString();
    }
}
